package yatan.cluster.job.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import yatan.cluster.job.Job;
import yatan.cluster.job.JobAuditor;

public class DefaultJobAuditor implements JobAuditor {
    private Logger logger = Logger.getLogger(DefaultJobAuditor.class.getName());

    private long totalSucessfulJobCount;
    private long totalFailedJobCount;
    private long lastSuccessfulJobCount;
    private long lastFailedJobCount;

    private long startTime = new Date().getTime();
    private long lastReportTime = new Date().getTime();

    private long reportInterval = 1 * 60 * 1000;

    private Map<Long, Long> jobStartTimes = new HashMap<Long, Long>();
    private long totalJobCount;
    private double averageRunningTime;

    public synchronized void audit(Job job, String action) {
        if (action.equals("start")) {
            this.jobStartTimes.put(job.getId(), new Date().getTime());
        } else if (action.equals("success")) {
            this.averageRunningTime =
                    ((this.averageRunningTime * this.totalJobCount) + (new Date().getTime() - this.jobStartTimes
                            .get(job.getId())))
                            / ++this.totalJobCount;

            this.lastSuccessfulJobCount++;
            this.totalSucessfulJobCount++;
        } else {
            this.averageRunningTime =
                    ((this.averageRunningTime * this.totalJobCount) + (new Date().getTime() - this.jobStartTimes
                            .get(job.getId())))
                            / ++this.totalJobCount;

            this.lastFailedJobCount++;
            this.totalFailedJobCount++;
        }

        long currentTime = new Date().getTime();
        if (currentTime - this.lastReportTime > this.reportInterval) {
            double runningTime = (currentTime - this.startTime) / 1000.0 / 60.0;
            double intervalTime = (currentTime - this.lastReportTime) / 1000.0 / 60.0;
            logger.info("In the last " + (int) intervalTime + " minutes: "
                    + (this.lastSuccessfulJobCount / intervalTime) + " success per minute, "
                    + (this.lastFailedJobCount / intervalTime) + " failure per minute.");
            logger.info("Already running " + (int) runningTime + " minutes: "
                    + (this.totalSucessfulJobCount / runningTime) + " success per minute, "
                    + (this.totalFailedJobCount / runningTime) + " failure per minute.");
            logger.info("Average job running time: " + this.averageRunningTime / 1000 + " s");

            this.lastReportTime = currentTime;
            this.lastSuccessfulJobCount = 0;
            this.lastFailedJobCount = 0;
        }
    }
}
